#include "Object.h"
#include "stdio.h"
#include "Define.h"
#include <math.h>

const float Object::k_Gravity = 1.0f;
const float Object::k_PixelPerMeter = 1.0f;
const float Object::k_FrictionPercent = 0.98f;
const float Object::k_MinVelocity = 0.01f;

Object::Object(void)
{
	this->m_iPositionX = 0;
	this->m_iPositionY = 0;
	this->m_iVelocity = 0; 
	this->m_Type = NONE;
	SetMass(k_DefaultMass);
	m_fAccelerationX = 0;
	m_fAccelerationY = 0;
	m_fVeloX = m_fVeloY = 0;
	m_isSelected = false;
}

Object::Object(float posX, float posY)
{
	this->m_iPositionX = posX;
	this->m_iPositionY = posY;
	this->m_iVelocity = 0;
	this->m_Type = NONE;
	SetMass(k_DefaultMass);
	m_fAccelerationX = 0;
	m_fAccelerationY = 0;
	m_fVeloX = m_fVeloY = 0;
	m_isSelected = false;
}

Object::~Object(void)
{
}

void Object::SetPosition(float iPosX, float iPosY)
{
	this->m_iPositionX = iPosX;
	this->m_iPositionY = iPosY;
}

void Object::SetVelocityDefault(float iVel)
{
	this->m_iVelocity = iVel;
}

void Object::MoveBy(float addX, float addY)
{
	SetPosition(m_iPositionX + addX, m_iPositionY + addY);
}

void Object::SetType(EObjectType type)
{
	this->m_Type = type;
}
EObjectType Object::GetType()
{
	return this->m_Type;
}

float Object::GetPosX()
{
	return m_iPositionX;
}
float Object::GetPosY()
{
	return m_iPositionY;
}

bool Object::IsCollideWithObject(Object* object)
{
	return false;
}

int Object::IsCollideEdge()
{
	return 0;
}

void Object::SetMass(int mass)
{
	this->m_iMass = mass;
}

void Object::SetAcceleration(float accX, float accY)
{
	this->m_fAccelerationX = accX;
	this->m_fAccelerationY = accY;
}

void Object::AddAcceleration(float accX, float accY)
{
	this->m_fAccelerationX += accX;
	this->m_fAccelerationY += accY;
}

void Object::AddForce(float forceX, float forceY)
{
	float accelerationX = forceX / m_iMass;
	float accelerationY = forceY / m_iMass;
	SetAcceleration(accelerationX, accelerationY);
}

void Object::AddVelo(float velX, float velY)
{
	m_fVeloX += velX;
	m_fVeloY += velY;
}

int Object::GetMass()
{
	return m_iMass;
}

bool Object::CheckFlag(int flag, int mask)
{
	int result = flag & mask;
	return (result != 0);
}

void Object::Update(float frameTime)
{
	//float accelerationY = m_fAccelerationY + k_Gravity;
	float accelerationY = m_fAccelerationY;
	if (!IsSelected())
	{
		accelerationY = k_Gravity;
	}
	float deltaTime = 1;

	float velocityX = 0;
	float velocityY = 0;
	float deltaX = 0;
	float deltaY = 0;
	
	//if (m_fVeloX != 0) 
	{
		m_fVeloX = m_fVeloX + m_fAccelerationX * deltaTime;

		deltaX = m_fVeloX * deltaTime; // + m_fAccelerationX * deltaTime * deltaTime * 0.5f;
		m_fVeloX *= k_FrictionPercent;
	}

	//if (m_fVeloY != 0) 
	{
		m_fVeloY = m_fVeloY + accelerationY * deltaTime;

		deltaY = m_fVeloY * deltaTime;// + accelerationY * deltaTime * deltaTime * 0.5f;
		m_fVeloY *= k_FrictionPercent;
	}
	MoveBy(deltaX * k_PixelPerMeter, deltaY * k_PixelPerMeter);

	/// TODO: cheat to stop object when mouse keep hold
	if (m_iDestPosX >=0 && m_iDestPosY >= 0 && IsInRect((int)m_iDestPosX, (int)m_iDestPosY))
	{
		SetVelocity(0, 0);
		SetAcceleration(0, 0);
		m_iDestPosX = m_iDestPosY = -1;
	}

	if (abs(m_fVeloX) < k_MinVelocity)
	{
		m_fVeloX = 0;
	}

	if (abs(m_fVeloY) < k_MinVelocity)
	{
		m_fVeloY = 0;
	}

	int hasCollide = IsCollideEdge();

	if (CheckFlag(hasCollide, BOTTOM) || CheckFlag(hasCollide, TOP))
	{
		m_fVeloY = -m_fVeloY;
		m_fAccelerationX = 0;
		m_fAccelerationY = 0;

	}

	if (CheckFlag(hasCollide, LEFT) || CheckFlag(hasCollide, RIGHT))
	{
		m_fVeloX = -m_fVeloX;
		m_fAccelerationX = 0;
		m_fAccelerationY = 0;
	}
	
}

float Object::GetVelocityDefault()
{
	return this->m_iVelocity;
}

void Object::SetVelocity(float velX, float velY)
{
	this->m_fVeloX = velX;
	this->m_fVeloY = velY;
}

void Object::SetDestPos(float posX, float posY)
{
	m_iDestPosX = posX;
	m_iDestPosY = posY;
}

float Object::GetCenterPosX()
{
	return m_iPositionX;
}

float Object::GetCenterPosY()
{
	return m_iPositionY;
}

void Object::SetSelect(bool select)
{
	m_isSelected = select;
}

bool Object::IsSelected()
{
	return m_isSelected;
}
